﻿<template>
  <div class="training-config">
    <div class="page-header">
      <h1 class="page-title gradient-text">⚙️ 训练配置</h1>
      <p class="page-desc">联邦学习模型参数与训练策略配置</p>
    </div>

    <div class="config-container">
      <div class="config-form">
        <div class="form-header">
          <div class="header-icon">🔧</div>
          <h3>训练参数配置</h3>
        </div>
        
        <div class="form-content">
          <!-- 左侧：基础配置 -->
          <div class="form-column">
            <div class="form-section compact">
              <div class="section-header">
                <span class="section-title">🎯 基础配置</span>
              </div>
              <div class="form-group">
                <!-- 模型选择和数据集放在同一行 -->
                <div class="form-row">
                  <div class="form-item">
                    <label class="form-label">模型选择</label>
                    <el-select v-model="configForm.model" class="form-input dark统一输入框样式">
                      <el-option label="CNN" value="CNN"></el-option>
                      <el-option label="ResNet-50" value="resnet50"></el-option>
                      <el-option label="BERT-Base" value="bert-base"></el-option>
                    </el-select>
                  </div>

                  <div class="form-item">
                    <label class="form-label">数据集</label>
                    <el-select v-model="configForm.dataset" class="form-input dark统一输入框样式">
                      <el-option label="MNIST" value="MNIST"></el-option>
                      <el-option label="CIFAR-10" value="CIFAR10"></el-option>
                      <el-option label="Fashion-MNIST" value="FashionMNIST"></el-option>
                    </el-select>
                  </div>
                </div>

                <!-- 随机种子和学习率放在同一行 -->
                <div class="form-row">
                  <div class="form-item">
                    <label class="form-label">随机种子</label>
                    <el-input-number 
                      v-model="configForm.seed"
                      :min="0"
                      controls-position="right"
                      class="form-input dark统一输入框样式">
                    </el-input-number>
                  </div>

                  <div class="form-item">
                    <label class="form-label">学习率</label>
                    <el-input-number 
                      v-model="configForm.lr"
                      :min="0.0001"
                      :max="0.1"
                      :step="0.0001"
                      controls-position="right"
                      class="form-input dark统一输入框样式">
                    </el-input-number>
                  </div>
                </div>
              </div>
            </div>

            <div class="form-section compact">
              <div class="section-header">
                <span class="section-title">⚡ 训练参数</span>
              </div>
              <div class="form-group">
                <!-- 批量大小和全局轮次放在同一行 -->
                <div class="form-row">
                  <div class="form-item">
                    <label class="form-label">批量大小</label>
                    <el-input-number 
                      v-model="configForm.batch_size"
                      :min="1"
                      :max="512"
                      controls-position="right"
                      class="form-input dark统一输入框样式">
                    </el-input-number>
                  </div>

                  <div class="form-item">
                    <label class="form-label">全局轮次</label>
                    <el-input-number 
                      v-model="configForm.global_communication_epochs"
                      :min="1"
                      :max="1000"
                      controls-position="right"
                      class="form-input dark统一输入框样式">
                    </el-input-number>
                  </div>
                </div>

                <!-- 本地轮次和客户端选择率放在同一行 -->
                <div class="form-row">
                  <div class="form-item">
                    <label class="form-label">本地轮次</label>
                    <el-input-number 
                      v-model="configForm.local_update_epochs"
                      :min="1"
                      :max="10"
                      controls-position="right"
                      class="form-input dark统一输入框样式">
                    </el-input-number>
                  </div>

                  <div class="form-item">
                    <label class="form-label">客户端选择率</label>
                    <el-select v-model="configForm.selected_rate" class="form-input dark统一输入框样式">
                      <el-option label="10%" :value="0.1"></el-option>
                      <el-option label="20%" :value="0.2"></el-option>
                      <el-option label="30%" :value="0.3"></el-option>
                      <el-option label="40%" :value="0.4"></el-option>
                      <el-option label="50%" :value="0.5"></el-option>
                      <el-option label="60%" :value="0.6"></el-option>
                      <el-option label="70%" :value="0.7"></el-option>
                      <el-option label="80%" :value="0.8"></el-option>
                      <el-option label="90%" :value="0.9"></el-option>
                      <el-option label="100%" :value="1.0"></el-option>
                    </el-select>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- 右侧：算法和客户端配置 -->
          <div class="form-column">
            <div class="form-section compact">
              <div class="section-header">
                <span class="section-title">🔬 算法配置</span>
              </div>
              <div class="algorithm-group">
                <div class="algorithm-options">
                  <div 
                    v-for="algo in algorithms" 
                    :key="algo.value"
                    :class="['algorithm-option', { active: configForm.algorithm === algo.value }]"
                    @click="configForm.algorithm = algo.value"
                  >
                    <div class="algo-icon">{{ algo.icon }}</div>
                    <div class="algo-info">
                      <div class="algo-name">{{ algo.name }}</div>
                      <div class="algo-desc">{{ algo.desc }}</div>
                    </div>
                  </div>
                </div>

                <div v-if="configForm.algorithm === 'fedprox'" class="param-item">
                  <label class="form-label">Proximal Mu</label>
                  <div class="param-control">
                    <el-input-number 
                      v-model="configForm.algorithm_params.prox_mu"
                      :min="0.001"
                      :max="1.0"
                      :step="0.001"
                      controls-position="right"
                      class="form-input dark统一输入框样式">
                    </el-input-number>
                  </div>
                </div>
              </div>
            </div>

            <div class="form-section compact">
              <div class="section-header">
                <span class="section-title">🌐 客户端配置</span>
                <span class="clients-count">{{ configForm.clients.length }}个</span>
              </div>
              <div class="clients-group">
                <div class="clients-list">
                  <div 
                    v-for="(client, index) in configForm.clients" 
                    :key="index" 
                    class="client-item"
                  >
                    <div class="client-info">
                      <span class="client-index">客户端 {{ index + 1 }}</span>
                      <el-input
                        v-model="client.address"
                        placeholder="IP地址:端口"
                        class="client-input dark统一输入框样式">
                      </el-input>
                    </div>
                    <el-button 
                      type="danger" 
                      text 
                      size="small"
                      @click="removeClient(index)"
                      class="remove-btn"
                      :disabled="configForm.clients.length <= 1">
                      删除
                    </el-button>
                  </div>
                </div>
                <el-button 
                  type="primary" 
                  text 
                  size="small"
                  @click="addClient"
                  class="add-btn">
                  + 添加客户端
                </el-button>
              </div>
            </div>
          </div>
        </div>

        <!-- 操作按钮 -->
        <div class="action-section">
          <div class="action-buttons">
            <el-button class="action-btn reset" @click="resetForm">
              🔄 重置配置
            </el-button>
            <el-button class="action-btn json" @click="showJson">
              📋 查看JSON
            </el-button>
            <el-button type="primary" class="action-btn submit" @click="startTraining">
              🚀 开始训练
            </el-button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'

// 算法配置
const algorithms = [
  { value: 'fedavg', name: 'FedAvg', desc: '联邦平均算法', icon: '⚖️' },
  { value: 'fedprox', name: 'FedProx', desc: '带近端正则化', icon: '🎯' },
  { value: 'feddyn', name: 'FedDyn', desc: '动态联邦学习', icon: '🔄' }
]

// 初始化配置表单
const configForm = reactive({
  model: 'CNN',
  dataset: 'MNIST',
  global_communication_epochs: 10,
  batch_size: 64,
  seed: 42,
  algorithm: 'fedprox',
  algorithm_params: { prox_mu: 0.01 },
  local_update_epochs: 2,
  selected_rate: 0.5,
  lr: 0.001,
  clients: [
    { address: "localhost:50051" },
    { address: "localhost:50052" }
  ]
})

// 添加客户端
const addClient = () => {
  const nextPort = 50053 + configForm.clients.length
  configForm.clients.push({ address: `localhost:${nextPort}` })
}

// 删除客户端
const removeClient = (index) => {
  if (configForm.clients.length > 1) {
    configForm.clients.splice(index, 1)
  } else {
    ElMessage.warning('至少需要保留一个客户端')
  }
}

// 重置表单
const resetForm = () => {
  ElMessageBox.confirm('确定要重置所有配置吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    Object.assign(configForm, {
      model: 'CNN',
      dataset: 'MNIST',
      global_communication_epochs: 10,
      batch_size: 64,
      seed: 42,
      algorithm: 'fedprox',
      algorithm_params: { prox_mu: 0.01 },
      local_update_epochs: 2,
      selected_rate: 0.5,
      lr: 0.001,
      clients: [
        { address: "localhost:50051" },
        { address: "localhost:50052" }
      ]
    })
    ElMessage.success('配置已重置')
  })
}

// 显示JSON
const showJson = () => {
  ElMessageBox.alert(JSON.stringify(configForm, null, 2), '训练请求JSON', {
    confirmButtonText: '确定',
    customClass: 'json-modal',
    width: '600px'
  })
}

// 开始训练
const startTraining = async () => {
  try {
    // 验证客户端地址格式
    for (const client of configForm.clients) {
      if (!client.address || !client.address.includes(':')) {
        ElMessage.error(`客户端地址格式错误: ${client.address}`)
        return
      }
    }

    console.log('发送训练配置:', configForm)
    
    const response = await fetch('/classification/trainConfig', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(configForm)
    })

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }

    const result = await response.json()
    
    if (result.code === 200) {
      ElMessage.success('训练任务已提交！')
      console.log('训练任务响应:', result)
    } else {
      throw new Error(result.message || '训练任务提交失败')
    }
    
  } catch (error) {
    console.error('训练任务提交失败:', error)
    ElMessage.error('训练任务提交失败: ' + error.message)
  }
}
</script>

<style scoped>
.training-config {
  padding: 20px;
  background: linear-gradient(135deg, #0c0e1a 0%, #1a1f35 50%, #0f1220 100%);
  min-height: 100vh;
  max-height: 100vh;
  overflow: hidden;
}

.page-header {
  text-align: center;
  margin-bottom: 20px;
  padding: 10px;
}

.page-title {
  font-size: 1.8em;
  margin-bottom: 5px;
  background: linear-gradient(45deg, #00f2fe, #9d50bb);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.page-desc {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.95em;
}

.config-container {
  max-width: 1000px;
  margin: 0 auto;
  height: calc(100vh - 120px);
}

.config-form {
  background: rgba(16, 18, 27, 0.9);
  border-radius: 12px;
  border: 1px solid rgba(79, 172, 254, 0.3);
  backdrop-filter: blur(10px);
  height: 100%;
  display: flex;
  flex-direction: column;
}

.form-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 15px 20px;
  background: linear-gradient(90deg, rgba(0, 242, 254, 0.1), rgba(157, 80, 187, 0.1));
  border-bottom: 1px solid rgba(79, 172, 254, 0.2);
}

.form-header h3 {
  margin: 0;
  color: #00f2fe;
  font-size: 1.1em;
}

.header-icon {
  font-size: 1.3em;
}

.form-content {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  padding: 0;
  overflow: hidden;
}

.form-column {
  padding: 15px;
  display: flex;
  flex-direction: column;
  gap: 15px;
  overflow-y: auto;
}

.form-column:first-child {
  border-right: 1px solid rgba(255, 255, 255, 0.1);
}

.form-section.compact {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 8px;
  padding: 15px;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.section-title {
  font-size: 0.95em;
  font-weight: bold;
  color: #00f2fe;
}

.clients-count {
  font-size: 0.8em;
  color: rgba(255, 255, 255, 0.5);
  background: rgba(0, 242, 254, 0.1);
  padding: 2px 6px;
  border-radius: 10px;
}

/* 表单组样式 */
.form-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* 表单项行布局 */
.form-row {
  display: flex;
  gap: 12px;
  width: 100%;
}

.form-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1; /* 让行内的表单项平分宽度 */
}

.form-label {
  font-size: 0.8em;
  font-weight: bold;
  color: rgba(255, 255, 255, 0.9);
}

/* 算法配置 */
.algorithm-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.algorithm-options {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}

.algorithm-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.algorithm-option:hover {
  border-color: rgba(79, 172, 254, 0.4);
  background: rgba(79, 172, 254, 0.05);
}

.algorithm-option.active {
  border-color: #00f2fe;
  background: rgba(0, 242, 254, 0.1);
}

.algo-icon {
  font-size: 1.2em;
}

.algo-name {
  font-weight: bold;
  color: #fff;
  font-size: 0.85em;
}

.algo-desc {
  font-size: 0.7em;
  color: rgba(255, 255, 255, 0.6);
  margin-top: 1px;
}

.param-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px;
  background: rgba(0, 242, 254, 0.05);
  border-radius: 6px;
  border: 1px solid rgba(0, 242, 254, 0.2);
}

.param-control {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* 客户端配置 */
.clients-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.clients-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 150px;
  overflow-y: auto;
}

.client-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px;
  background: rgba(255, 255, 255, 0.05);
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.client-info {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
}

.client-index {
  font-size: 0.75em;
  font-weight: bold;
  color: #00f2fe;
  min-width: 60px;
}

.add-btn {
  width: 100%;
  margin-top: 5px;
  font-size: 0.8em;
}

/* 操作按钮 */
.action-section {
  padding: 15px 20px;
  background: rgba(0, 0, 0, 0.2);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.action-buttons {
  display: flex;
  justify-content: center;
  gap: 10px;
}

.action-btn {
  padding: 8px 16px;
  font-size: 0.85em;
  border-radius: 6px;
  transition: all 0.2s ease;
}

.action-btn.submit {
  background: linear-gradient(45deg, #00f2fe, #9d50bb);
  border: none;
  color: #fff;
}

.action-btn.submit:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(157, 80, 187, 0.3);
}

.action-btn.reset {
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: rgba(255, 255, 255, 0.8);
}

.action-btn.json {
  background: rgba(79, 172, 254, 0.1);
  border: 1px solid rgba(79, 172, 254, 0.3);
  color: #4facfe;
}

.action-btn.reset:hover,
.action-btn.json:hover {
  background: rgba(255, 255, 255, 0.15);
  transform: translateY(-1px);
}

/* 统一所有输入框样式（基于随机种子输入框的样式） */
:deep(.dark统一输入框样式 .el-input__wrapper),
:deep(.dark统一输入框样式 .el-select__wrapper) {
  background: rgba(255, 255, 255, 0.05) !important;
  border: 1px solid rgba(255, 255, 255, 0.15) !important;
  border-radius: 4px !important;
  box-shadow: none !important;
  width: 100% !important;
}

:deep(.dark统一输入框样式 .el-input__wrapper:hover),
:deep(.dark统一输入框样式 .el-select__wrapper:hover) {
  border-color: rgba(79, 172, 254, 0.4) !important;
}

:deep(.dark统一输入框样式 .el-input__wrapper.is-focus),
:deep(.dark统一输入框样式 .el-select__wrapper.is-focus) {
  border-color: #00f2fe !important;
  box-shadow: 0 0 0 1px rgba(0, 242, 254, 0.1) !important;
}

:deep(.dark统一输入框样式 .el-input__inner),
:deep(.dark统一输入框样式 .el-select__inner) {
  color: #fff !important;
  background: transparent !important;
  font-size: 0.85em;
}

:deep(.dark统一输入框样式 .el-input__inner::placeholder),
:deep(.dark统一输入框样式 .el-select__placeholder) {
  color: rgba(255, 255, 255, 0.4) !important;
}

:deep(.dark统一输入框样式 .el-input-number) {
  width: 100% !important;
}

:deep(.el-form-item) {
  margin-bottom: 0;
}

.json-modal :deep(.el-message-box__message) {
  font-family: 'Courier New', monospace;
  background: #1a1a1a;
  color: #00f2fe;
  padding: 15px;
  border-radius: 4px;
  white-space: pre-wrap;
  text-align: left;
}

/* 滚动条优化 */
.form-column::-webkit-scrollbar,
.clients-list::-webkit-scrollbar {
  width: 4px;
}

.form-column::-webkit-scrollbar-track,
.clients-list::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 2px;
}

.form-column::-webkit-scrollbar-thumb,
.clients-list::-webkit-scrollbar-thumb {
  background: linear-gradient(45deg, #00f2fe, #4facfe);
  border-radius: 2px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .form-content {
    grid-template-columns: 1fr;
  }
  
  .form-column:first-child {
    border-right: none;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  }
  
  .action-buttons {
    flex-direction: column;
  }
  
  /* 响应式调整：小屏幕下将行内元素改为单列 */
  .form-row {
    flex-direction: column;
    gap: 12px;
  }
}
</style>